/**
 *
 * <p>Title: Base64 </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>Company: </p>
 *
 * @author David So
 * @version 1.0
 */


public class Base64 {
  final private static char[] trans_tbl = {
      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
      'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
      'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
      'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
      'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
      '+', '/'};

  final private static void encode_helper(char[] src, int src_idx, char[] dst,
                                          int dst_idx, int count) {
    int data = 0;

    switch (count) {
      case 1:
        data = src[src_idx] << 4;
        break;

      case 2:
        data = (src[src_idx] << 10) | (src[src_idx] << 2);
        break;

      case 3:
        data = (src[src_idx] << 16) | (src[src_idx + 1] << 8) |
            (src[src_idx + 2]);
        break;
    }

    for (int i = 6 * count; i >= 0; i -= 6) {
      dst[dst_idx++] = trans_tbl[ (data >>> i) & 0x3f];
    }

    for (int i = 0; i < (3 - count); i++) {
      dst[dst_idx++] = '=';
    }
  }

  /**
   * This method encodes a string using Base64.
   *
   * @param in_str the string to encode.
   * @return       the encoded string
   */

  final public static String encode(char[] in_str) {
    int out_count = 4 * (in_str.length / 3 +
                         ( (in_str.length % 3) > 0 ? 1 : 0));

    char[] out_str = new char[out_count];
    int out_idx = 0;

    for (int i = 0; i < in_str.length; i += 3, out_idx += 4) {
      int count = (in_str.length - i) < 3 ? in_str.length - i : 3;
      encode_helper(in_str, i, out_str, out_idx, count);
    }

    return new String(out_str);
  }

  /**
   * This method encodes a string using Base64.
   *
   * @param in_str the string to encode.
   * @return       the encoded string
   */
  final public static String encode(String in_str) {
    return encode(in_str.toCharArray());
  }

}
